use Action;


### Alters the characteristics of a map tile
### The way it is altered depends on the parameters
###
### For the time being, it just adds or destroys walls (replaces the tile)
###
### Given parameters must be:
###
### ---- ENTITY: A reference to the entity performing the action
### ---- MAP A reference to the map to be placed on
### ---- DIRECTION: UP | DOWN | LEFT | RIGHT
###
### ---------------------------------------------------------
### =========================================================
package BuildAction;

@ISA = qw/Action/;
our @DEPENDS_ON = qw/MapManager EntityManager LogManager InputManager/;

sub perform{
    my $self=shift;
    my $lm = $self->{"LogManager"};

    my ($entity, $map, $dir, $wellKnownEntity) = ($self->params->{ENTITY},
							$self->params->{MAP},
							$self->params->{DIRECTION},
							$self->params->{WELL_KNOWN_ENTITY});

    my $result = undef;
    my $entity = undef;
    # An Entity to be moved, specified either directly or through
    # the name of a well known entity within the EntityManager
    if(! (defined $entity)){
	if(! (defined $wellKnownEntity)){
	    $result = "FAILURE";
	    $msg = "BuildAction: ENTITY or WELL_KNOWN_ENTITY not defined\n";
	    $lm->log($msg);
	}else{
	    $entity = $self->{EntityManager}->entities($wellKnownEntity)->[0];
	    if(! defined $entity){
		$result = "FAILURE";
		$msg = "BuildAction: ENTITY - reference expected, but was undefined";
		$lm->log($msg);
	    } # if well known entity did not exist
	    else {
		$self->params->{ENTITY} = $entity;
		$lm->log("Well known entity ".$wellKnownEntity."found: ".$entity);
	    } # if well known entity existedp
	} # if no entity was specified, specific or by well known name
    } # if no specific entity was given


    # A map where the movement takes place, specified either directly
    # or the currently selected map within the MapManager
    if(! ((defined $map) and (ref $map eq 'Map')) ){
	my $selectedMap = $self->{MapManager}->selected;
	if(defined $selectedMap){
	    $self->params->{MAP} = $selectedMap;
	    $map = $selectedMap;

	    $lm->log("Selected map found: ".$map);
	} else{
	    $result = "FAILURE";
	    $msg = "BuildAction: MAP - reference to a map expected, found ".(ref $map)." and no map selected in MapManager";
	    $lm->log($msg);
	}
    }

    unless(defined $dir){

	$lm->log("BuildAction: Waiting for direction");

	# Ask for a direction
	my $input = $self->{"InputManager"};
	my $command = undef;

	$lm->log("BuildAction: Setting new keyb bindings");
	$input->pushBindings("MENU_BASIC");
	my $waitingForDirection = 1;
	while($waitingForDirection){
	    $command = $input->waitForKeyCommand;
	    next unless $command;

#	    $lm->log("BuildAction: Command received: ".$command);
	    if($command eq "Up" || $command eq "Down" || $command eq "Left" || $command eq "Right"){
		$self->{DIRECTION} = uc($command);
		$dir = uc($command);

		$waitingForDirection = 0;
#		$lm->log("BuildAction: Command received");
#		$lm->log("BuildAction: Direction specified");
	    } # switch command
	} # waiting for command

	$lm->log("BuildAction: Returning to old keyb bindings");
	$input->popBindings;

#	$result = ActionResult->new("FAILURE", $msg);
#	$lm->log($msg);
    }

    unless(defined $result){
	$result = ActionResult->new("SUCCESS", "OK");
    }

    # Calculate and store the target position
    my $pos = $entity->pos;
    my $newPos = $self->getNewPos($pos, $dir, $map->width, $map->height);
    $self->params->{POS} = $newPos;

    # Check out coordinates of bounds
    my ($w, $h) = ($map->width, $map->height);
    if($newPos[0] < 0 || $newPos[0] > $w || $newPos[1] < 0 || $newPos[1] > $h){
	$result = ActionResult->new("FAILURE", "Building outside of the map!");
    }

    return $result unless($result->is("SUCCESS"));

    #OPERATION: TOGGLE WALL 

    my  $result = ActionResult->new("DONE", "OK");
    return $result;
}



## Calculates the new position,
## based on the direction, the 
## old position, the map's height
## and width
##
## Parameters:
##    oldPosition : Array reference [X, Y]
##    direction : scalar
##    height, width : scalars
sub getNewPos{
    my $self = shift;
    my $oldPos = shift;
    my $dir = shift;
    my ($w, $h) = (shift, shift);

    my $newPos = [$oldPos->[0], $oldPos->[1]];
    if($dir eq "UP"){
	$newPos->[1] -= 1;
    }
    if($dir eq "DOWN"){
	$newPos->[1] += 1;
    }
    if($dir eq "LEFT"){
	$newPos->[0] -= 1;
    }
    if($dir eq "RIGHT"){
	$newPos->[0] += 1;
    }
    return $newPos;
}
